package com.mdhw.mili.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.mdhw.ali.service.AliService;
import com.mdhw.common.base.MiliPageData;
import com.mdhw.common.base.PageData;
import com.mdhw.common.contants.CacheKeyContants;
import com.mdhw.config.R;
import com.mdhw.guanlin.entity.GuanUser;
import com.mdhw.guanlin.service.GuanUserService;
import com.mdhw.guanlin.vo.GuanUserVo;
import com.mdhw.guanlin.vo.GuanlinMiliLoginVo;
import com.mdhw.mili.service.MiliService;
import com.mdhw.mili.vo.area.CityVo;
import com.mdhw.mili.vo.area.ParksVo;
import com.mdhw.mili.vo.area.VisitorVo;
import com.mdhw.mili.vo.system.DictDataVo;
import com.mdhw.mili.vo.system.FaceCheckVo;
import com.mdhw.mili.vo.system.ReturnVo;
import com.mdhw.mili.vo.user.*;
import com.mdhw.utils.JwtUtil;
import com.mdhw.utils.OkHttpUtil;
import com.mdhw.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

@Slf4j
@Service
public class MiliServiceImpl implements MiliService {


    private String host = "https://icloud.aurine.cn:19000";

    private String token_social = host + "/auth/mobile/token/socia";        // 登录

    private String register = host + "/pmd/login/register";                 // 注册

    private String all_visitor = host + "/pmd/project/page/all/visitor";                        // 查询所有小区

    private String get_visitor_by_mobile = host + "/pmd/visitor/getVisitorInfoByMobileNo";              //  通过电话号码获取当前访客信息

    private String get_city_list = host + "/pmd/project/city/list";                 // 查询已开通的城市列表

    private String get_house_info = host + "/pmd/house/info";                       // 查询业主信息
    private String get_all_parks = host + "/pmd/visitor/getAllParks";                       // 获取车场信息

    private String get_dict_by_type = host + "/admin/dict/type/";                 // 查询数据字典

    private String visitor_check_pass_right = host + "/pmd/visitor/checkPassRight";     // 通过手机号查询访客的通行信息

    private String add_visitor_by_phone = host + "/pmd/visitor/addVisitorByPhone/";          // 登录后判断是否有访客账号，新增访客

    private String page_by_visitor = host + "/pmd/visitor/pageByVisitor";                   // 访客申请记录
    private String register_by_visitor = host + "/pmd/visitor/registerByVisitor";           //  访客申请
    private String face_upload_and_check     = host + "/face/face/uploadAndCheck/";           //  人脸验证

    private String get_authorized_face_fk = host + "/pmd/user/getAuthorizedFaceFk";             // 获取人脸协议

    private String visitor_notification = host + "/pmd/visitor/visitorNotification";                   // 访客首页- 访客通知
    private String get_visitor_qrcode = host + "/pmd/device/qr-code/visitor/";                   // 获取访客二维码
    private String mili_get_openid = host + "/admin/user/openid";                   //  米立根据设备号获取 用户 ID

    private String  get_visitor_label = host + "/pmd/visitor/visitorLabel";                           // 获取来访事由标签
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private AliService aliService;

    @Autowired
    private GuanUserService guanUserService;

//    public String register(String code,){
//
//    }

    /**
     * 直接 登录
     * @param guanlinMiliLoginVo
     */
    @Override
    public R<GuanUserVo>  tokenSocial(GuanlinMiliLoginVo guanlinMiliLoginVo)
    {
        String mobileJiami = guanlinMiliLoginVo.getMobile();
        String code = guanlinMiliLoginVo.getCode();

        R returnVo = R.errorReturnYuan("！登录失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String mobileParams = "ALIPAY@"+ mobileJiami;
        String url = this.token_social;
        Map params = new HashMap();
        params.put("type","ALIPAY");
        params.put("code",mobileJiami);

        log.info("米立接口 登录 参数  : {}", JSONObject.toJSONString(params));
        Map<String,String> headers = new HashMap();
        headers.put("Authorization","Basic QUxJUEFZOkFMSVBBWQ==");
        String serialNumber = guanlinMiliLoginVo.getSerialNumber();

        String openId = "";
        // 支付宝获取  Openid
        try {
//            AlipaySystemOauthTokenResponse alipaySystemOauthTokenResponse = this.aliService.getAuthCode(code);
//            if(alipaySystemOauthTokenResponse.isSuccess()){
//                openId = alipaySystemOauthTokenResponse.getOpenId();
//            }
            Response response = okHttpUtil.postDataWithBodyWithHeader(url, params, headers);
            String resultStr = response.body().string();
            log.info("米立登录 返回值 ： {}",resultStr);

            if(response.isSuccessful()){

                TokenSociVo tokenSociVo = JSONObject.parseObject(resultStr, TokenSociVo.class);
                //TokenSociVo tokenSociVo = new TokenSociVo();
                String miliUserToken = tokenSociVo.getToken_type()+" "+tokenSociVo.getAccess_token();

                Boolean isHaveOpenId = Boolean.FALSE;

                UserInfoVo userInfo = tokenSociVo.getUser_info();
                if(userInfo == null){
                    userInfo = new UserInfoVo();
                } else  {
                    String alipayOpenid = userInfo.getAlipayOpenid();
                    if(StringUtils.isBlank(alipayOpenid)){
                        R useropenidResult = this.useropenid(code, userInfo.getId(), miliUserToken);
                        if(useropenidResult.getCode() == 0){
                            isHaveOpenId = Boolean.TRUE;
                        }else{
                            isHaveOpenId = Boolean.FALSE;
                        }
                    }else{
                        isHaveOpenId = Boolean.TRUE;
                    }
                }
                if(!isHaveOpenId){
                    return R.errorReturnYuan("！登录失败，获取不到用户 openid");
                }

                GuanUserVo guanUserVo = this.guanUserService.saveGuanUser(tokenSociVo);
                guanUserVo.setMiliUserInfo(userInfo);
                guanUserVo.setZfbOpenId(openId);
                redisUtil.set(CacheKeyContants.GUANLIN_MILI_USER_TOKEN+guanUserVo.getId(),miliUserToken,60*60*24*30);


                // 登录后判断是否有访客账号，新增访客
                R addVisitorResult = this.visitoraddVisitorByPhone(userInfo.getPhone(), miliUserToken, "1000006700");
                log.info("新增访客结果 {}",addVisitorResult);
//
//                //通过手机号查询访客的通行信息
                R<CheckPassRightVo> checkPassRightResult = this.selectVisitorCheckPassRight(userInfo.getPhone(), serialNumber,miliUserToken);

                log.info("通过手机号查询访客的通行信息 {}",checkPassRightResult);

                CheckPassRightVo checkPassRightVo = new CheckPassRightVo();
                checkPassRightVo.setCode(1);
                checkPassRightVo.setQrcodeStr("");
                checkPassRightVo.setProjectId(0);
                checkPassRightVo.setVisitId("0");
                checkPassRightVo.setProjectName("");
                if(checkPassRightResult.getCode() == 0){
                    guanUserVo.setCheckPassRightVo(checkPassRightResult.getData());
                }else {
                    guanUserVo.setCheckPassRightVo(checkPassRightVo);
                }
                return R.success(guanUserVo);

            }else{
                returnVo.setMsg(JSONObject.parseObject(resultStr).getString("msg"));
                return returnVo;
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }


    public R useropenid(String code ,Integer userid,String miliToken){
        R returnVo = R.errorReturnYuan("！绑定失败");

        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.mili_get_openid;
        Map params = new HashMap();

        params.put("userId", userid);
        params.put("code", code);
        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");

        try {
            log.info("根据设备号获取用户 id url  {}", url);
            String resultStr = this.sendPutRequest(url,JSONObject.toJSONString(params),headers);
            log.info("根据设备号获取用户 id 返回值  {}", resultStr);

            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
            }
            return null;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 选择小区
     * @param current
     * @param size
     * @param name
     * @param provinceCode
     * @param cityCode
     * @param countyCode
     * @param streetCode
     * @param userId
     * @param type
     * @param cityName
     * @return
     */
    @Override
    public R<MiliPageData<VisitorVo>> selectAllVisitorPage(Integer current, Integer size, String name, String provinceCode, String cityCode,
                                  String countyCode, String streetCode, Long userId, String type, String cityName, String miliToken) {
        try {
        R returnVo = new R();
        returnVo.setCode(1);
        returnVo.setMsg("！查询所有小区失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.all_visitor+"?";
        url = url+ "current="+ current +"&size="+size;
        if(StringUtils.isNotBlank(name)){
            try {
                url = url + "&name="+URLEncoder.encode(name,"UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
        if(StringUtils.isNotBlank(provinceCode)){
            url = url + "&provinceCode="+provinceCode;
        }
        if(StringUtils.isNotBlank(cityCode)){
            url = url + "&cityCode="+cityCode;
        }
        if(StringUtils.isNotBlank(countyCode)){
            url = url + "&countyCode="+countyCode;
        }
        if(StringUtils.isNotBlank(streetCode)){
            url = url + "&streetCode="+streetCode;
        }
        if(userId != null){
            url = url + "&userId="+userId;
        }
        if(type != null){
            url = url + "&type="+type;
        }
        if(StringUtils.isNotBlank(cityName)){
            url = url + "&cityName="+URLEncoder.encode(cityName,"UTF-8");
        }
        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");

            log.info("查询小区 url  {}", url);
            String resultStr = this.sendGetRequest(url,headers);
            //log.info("查询小区 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
//                if(jsonObject.getInteger("code") == 0){
//                    String dataStr = jsonObject.getString("data");
//
//                    MiliPageData miliPageData = JSONObject.parseObject(dataStr, MiliPageData.class);
//                    return miliPageData;
//                }
            }
            return null;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 通过手机号获取访客信息
     * @param fangkeMobile
     * @return
     */
    @Override
    public R<FangkeVo> selectFangkeByMobile(String fangkeMobile,String miliToken,String projectId) {

        R returnVo = R.errorReturnYuan("！手机号获取访客信息");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.get_visitor_by_mobile+"?mobileNo="+fangkeMobile;
        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        headers.put("PROJECT-ID",projectId);
        try {

            String resultStr = this.sendGetRequest(url,headers);
            //log.info("查询小区 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
            }
            return returnVo;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<CityVo> selectCityList(String name,String provinceCode,String cityCode,String streetCode,String cityName,String miliToken,String projectId) {
        try {
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.get_city_list+"?name=";
        if(StringUtils.isNotBlank(name)){
            url = url+URLEncoder.encode(name,"UTF-8");;
        }
        if(StringUtils.isNotBlank(provinceCode)){
            url = url+"&provinceCode="+provinceCode;
        }
        if(StringUtils.isNotBlank(cityCode)){
            url = url+"&cityCode="+cityCode;
        }
        if(StringUtils.isNotBlank(streetCode)){
            url = url+"&streetCode="+streetCode;
        }
        if(StringUtils.isNotBlank(cityName)){
            url = url+"&cityName="+URLEncoder.encode(cityName,"UTF-8");
        }
        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        headers.put("PROJECT-ID",projectId);


            String resultStr = this.sendGetRequest(url,headers);
            //log.info("查询小区 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                JSONObject jsonObject = JSONObject.parseObject(resultStr);
                if(jsonObject.getInteger("code") == 0){
                    String dataStr = jsonObject.getString("data");

                    List<CityVo> cityVoList = JSONObject.parseArray(dataStr, CityVo.class);
                    return cityVoList;
                }
            }
            return null;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public R<List<YezhuVo>> selectYezhuVo(String name, String miliToken, String projectId) {
        R returnVo = R.errorReturnYuan("！查询业主信息失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();

        try {
            String url = this.get_house_info+"?name="+ URLEncoder.encode(name,"UTF-8");
            Map params = new HashMap();

            Map<String,String> headers = new HashMap();
            headers.put("Authorization",miliToken);
            headers.put("TENANT-ID","1");
            headers.put("PROJECT-ID",projectId);
            log.info("查询业主 url   {}", url);
            log.info("查询业主 headers   {}", JSONObject.toJSONString(headers));

            String resultStr = this.sendGetRequest(url,headers);
            log.info("查询业主 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
            }
            return returnVo;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<ParksVo> selectParksList(String miliToken, String projectId) {
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.get_all_parks;

        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        headers.put("PROJECT-ID",projectId);
        try {

            String resultStr = this.sendGetRequest(url,headers);
            //log.info("查询小区 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                JSONObject jsonObject = JSONObject.parseObject(resultStr);
                if(jsonObject.getInteger("code") == 0){
                    String dataStr = jsonObject.getString("data");

                    List<ParksVo> parksVoList = JSONObject.parseArray(dataStr, ParksVo.class);
                    return parksVoList;
                }
            }
            return null;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<List<VisitorReasonVo>> selectVisitorLabel(String miliToken,String projectId) {
        R returnVo = R.errorReturnYuan("！查询来访事由失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.get_visitor_label;
        log.info("查询来访事由 url   {}", url);
        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);

        headers.put("TENANT-ID","1");
        if(StringUtils.isNotBlank(projectId)){
            headers.put("PROJECT-ID",projectId);
        }
        log.info("查询来访事由 请求头   {}",  JSONObject.toJSONString(headers));

        try {
            String resultStr = this.sendGetRequest(url,headers);
            log.info("查询来访事由 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
            }
            return returnVo;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public R<List<DictDataVo>> selectDictDataList(String dictType,String miliToken) {
        R returnVo = R.errorReturnYuan("！查询字典失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.get_dict_by_type+dictType;
        log.info("查询字典 url   {}", url);
        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);

        headers.put("TENANT-ID","1");
        try {

            String resultStr = this.sendGetRequest(url,headers);
//            log.info("查询字典 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
            }
            return returnVo;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 通过手机号查询访客的通行信息
     * @param phone             手机
     * @param serialNumber      支付宝设备序列号
     * @return
     */
    @Override
    public R<CheckPassRightVo> selectVisitorCheckPassRight(String phone, String serialNumber,String miliToken) {

        R returnVo = R.errorReturnYuan("！手机号查询访客的通行信息失败");

        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.visitor_check_pass_right;
        Map params = new HashMap();

        params.put("phone", phone);
        params.put("serialNumber", serialNumber);
        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");

        log.info("查询访客的通行信息  请求头 1 {} ",JSONObject.toJSONString(headers));
        log.info("查询访客的通行信息  参数 1 {} ",JSONObject.toJSONString( params));

        try {
            Response response = okHttpUtil.postDataWithBodyWithHeader(url, params, headers);

            if(response.isSuccessful()){
                String resultStr = response.body().string();
                log.info("查询访客的通行信息  返3 {} ",resultStr);

                returnVo = JSONObject.parseObject(resultStr,R.class);
                JSONObject jsonObject = JSONObject.parseObject(resultStr);
                String dataStr = jsonObject.getString("data");
                CheckPassRightVo checkPassRightVo = JSONObject.parseObject(dataStr, CheckPassRightVo.class);
                returnVo.setData(checkPassRightVo);
                return returnVo;
            }else{
                return returnVo;
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }


    /**
     * 登录后判断是否有访客账号，新增访客
     * @param phone
     * @param miliToken
     * @param projectId
     * @return
     */
    private R visitoraddVisitorByPhone(String phone,String miliToken,String projectId) {

        R returnVo = R.errorReturnYuan("！新增访客失败");


        String url = this.add_visitor_by_phone+phone;

        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        headers.put("PROJECT-ID",projectId);
        try {

            String resultStr = this.sendGetRequest(url,headers);
            //log.info("查询小区 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
            }
            return returnVo;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 访客申请
     * @param fangkeRegisterVo
     * @param miliToken
     * @param projectId
     * @return
     */
    @Override
    public R registerByVisitor(FangkeRegisterVo fangkeRegisterVo, String miliToken, String projectId) {
        R returnVo = R.errorReturnYuan("！访客申请失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.register_by_visitor;

        fangkeRegisterVo.setIsCode("0");
        String fangkeRegisterVoJSONStr = JSONObject.toJSONString(fangkeRegisterVo);
        Map params = new HashMap();
        params = JSONObject.parseObject(fangkeRegisterVoJSONStr,Map.class);

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        if(StringUtils.isNotBlank(projectId)){
            headers.put("PROJECT-ID",projectId);
        }
        String visitPinLv = fangkeRegisterVo.getVisitPinLv();
        if(StringUtils.isNotBlank(visitPinLv)){
            String period = this.laifangPeriod(fangkeRegisterVo.getVisitPinLv(), fangkeRegisterVo.getStartTime(), fangkeRegisterVo.getEndTime(), fangkeRegisterVo.getChongfu());
            params.put("period",period);
        }else {
            params.put("period","");
        }

        log.info("访客申请   请求头 {} ",JSONObject.toJSONString( headers));

        try {
            log.info("访客申请   参数 {} ",JSONObject.toJSONString(params));

            Response response = okHttpUtil.postDataWithBodyWithHeader(url, params, headers);
            String resultStr = response.body().string();
            log.info("访客申请   返回值 response {} ",resultStr);

            if(response.isSuccessful()){
                log.info("访客申请   返回值 str {} ",resultStr);

                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
            }else{
                return returnVo;
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据来访频率生成  cron 表达式
     * @param visitPinLv
     * @param startTime
     * @param endTime
     * @param chongfu
     * @return
     */
    private String laifangPeriod(String visitPinLv,String startTime,String endTime,String chongfu) {
        String period = "";
        String[] startTimeArr = startTime.split(":");  // 根据冒号分割字符串
        String startHour = startTimeArr[0];  // 获取冒号前面的部分

        String[] endTimeArr = endTime.split(":");  // 根据冒号分割字符串
        String endHour = endTimeArr[0];  // 获取冒号前面的部分
        if("1".equals(visitPinLv)){
            // 每天
            period = generateCronExpression("*","*",startHour+"-"+endHour,"*","*","?");
        }else if("2".equals(visitPinLv)){
            // 每周
            period = generateCronExpression("*","*",startHour+"-"+endHour,"?","*",chongfu);
        }else if("3".equals(visitPinLv)){
            // 每月
            period = generateCronExpression("*","*",startHour+"-"+endHour,chongfu,"*","?");
        }
        return period;
    }

    private  String generateCronExpression(String second, String minute, String hour, String dayOfMonth, String month, String dayOfWeek) {
        return second+" "+minute+" "+hour+" "+dayOfMonth+" "+ month+" "+dayOfWeek;
    }



    /**
     * 人脸上传校验
     * @param multipartFile
     * @param miliToken
     * @param projectId
     * @return
     */
    public R<FaceCheckVo> faceUploadAndCheck(MultipartFile multipartFile, String miliToken, String projectId) {
        R returnVo = R.errorReturnYuan("！人脸校验失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.face_upload_and_check+"out";



        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        if(StringUtils.isNotBlank(projectId)){
            headers.put("PROJECT-ID",projectId);
        }

        // 获取文件名
        String originalFileName = multipartFile.getOriginalFilename();

        // 生成一个新的文件名，避免文件名冲突
        String newFileName = System.currentTimeMillis() + "_" + originalFileName;

        // 指定文件保存路径
        File file = new File("/srv/www/mili/api/uploads/" + newFileName);

        // 创建目录
        file.getParentFile().mkdirs();






        // 将 MultipartFile 保存为 File
        Map<String,Object> params = new HashMap();
        log.info("人脸上传并校验 请求头 : {}", JSONObject.toJSONString(headers));

        try {
            multipartFile.transferTo(file);

            FileInputStream fileInputStreamReader = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()]; // 创建一个字节数组来存储图片数据
            fileInputStreamReader.read(bytes); // 读取图片文件并存储到字节数组中
            String imageBase64 = Base64.getEncoder().encodeToString(bytes);


            log.info("人脸上传并校验 url : {}",url);
            Map<String,Object> fileMap = new HashMap<>();
            fileMap.put("file",file);
            String resultStr = this.sendMultipartData2(url, params, headers, file);
            //String resultStr = this.sendMultipartData2(url, params, headers, file);
            log.info("人脸上传并校验 返回值 : {}",resultStr);
            if (file.exists() && file.delete()){

            }
            if(StringUtils.isNotBlank(resultStr)){


                returnVo = JSONObject.parseObject(resultStr,R.class);
                if(returnVo.getCode() == 0){
                    JSONObject jsonObject = JSONObject.parseObject(resultStr);
                    FaceCheckVo faceCheckVo = jsonObject.getObject("data", FaceCheckVo.class);
                    faceCheckVo.setImageBase64(imageBase64);
                    returnVo.setData(faceCheckVo);
                }
            }
            return returnVo;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }


    @Override
    public R<MiliPageData< FangkeLogVo>> selectFangkeLogPage(Integer current, Integer size, String name,String miliToken) {

        try {


        R returnVo = new R();
        returnVo.setCode(1);
        returnVo.setMsg("！查询访客记录失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.page_by_visitor+"?";
        url = url+ "current="+ current +"&size="+size;
        if(StringUtils.isNotBlank(name)){
            url = url + "&name="+URLEncoder.encode(name,"UTF-8");;
        }

        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");

            log.info("查询访客记录 url  {}", url);
            String resultStr = this.sendGetRequest(url,headers);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
            }
            return null;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 首页访客记录
     * @param current
     * @param size
     * @param name
     * @param miliToken
     * @return
     */
    @Override
    public R<List< IndexFangkeLogVo>> selectIndexFangkeLogPage(Integer current, Integer size, String name,String date,String status,String miliToken) {

        List< IndexFangkeLogVo> returnList = new ArrayList<>();
        IndexFangkeLogVo indexFangkeLogVo0 = new IndexFangkeLogVo();
        indexFangkeLogVo0.setIsPass("0");
        indexFangkeLogVo0.setIsPassName("可通行");
        indexFangkeLogVo0.setFangkeLogVoList(new ArrayList<>());
        List<FangkeLogVo> fangkeLogVoList0 = new ArrayList<>();

        IndexFangkeLogVo indexFangkeLogVo1 = new IndexFangkeLogVo();
        indexFangkeLogVo1.setIsPass("1");
        indexFangkeLogVo1.setIsPassName("待生效");
        indexFangkeLogVo1.setFangkeLogVoList(new ArrayList<>());
        List<FangkeLogVo> fangkeLogVoList1 = new ArrayList<>();

        returnList.add(indexFangkeLogVo0);
        returnList.add(indexFangkeLogVo1);


        try {
        R returnVo = R.errorReturnYuan("！查询首页访客记录");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.page_by_visitor+"?";
        url = url+ "current="+ current +"&size="+size;
        if(StringUtils.isNotBlank(name)){
            url = url + "&name="+URLEncoder.encode(name,"UTF-8");;
        }

        if(StringUtils.isNotBlank(date)){
            url = url + "&date="+date;
        }
        if(StringUtils.isNotBlank(status)){
            url = url + "&status="+status;
        }
        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        log.info("查询首页访客记录 请求头  {}",  JSONObject.toJSONString(headers));


            log.info("查询首页访客记录 url  {}", url);
            String resultStr = this.sendGetRequest(url,headers);
            //log.info("查询首页访客记录 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                JSONObject resultJson = JSONObject.parseObject(resultStr);
                if(resultJson.getInteger("code") == 0){
                    // 请求成功
                    JSONObject dataJson = resultJson.getJSONObject("data");
                    if(dataJson != null){
                        JSONArray recordsJsonArr = dataJson.getJSONArray("records");
                        if(recordsJsonArr != null && recordsJsonArr.size() > 0){
                            for(Object record : recordsJsonArr){
                                String recordJsonStr = JSONObject.toJSONString(record);
                                FangkeLogVo fangkeLogVo = JSONObject.parseObject(recordJsonStr, FangkeLogVo.class);
                                String isPass = fangkeLogVo.getIsPass();
                                if("0".equals(isPass)){
                                    // 可通行
                                    fangkeLogVoList0.add(fangkeLogVo);
                                }else if("1".equals(isPass)){
                                    fangkeLogVoList1.add(fangkeLogVo);
                                }
                            }
                            returnList = new ArrayList<>();
                            indexFangkeLogVo0.setFangkeLogVoList(fangkeLogVoList0);
                            indexFangkeLogVo1.setFangkeLogVoList(fangkeLogVoList1);
                            returnList.add(indexFangkeLogVo0);
                            returnList.add(indexFangkeLogVo1);
                            return R.success(returnList);
                        }
                    }

                }
                return R.success(returnList);
            }
            return R.success(returnList);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 获取人脸协议
     * @param miliToken
     * @param projectId
     * @return
     */
    @Override
    public R getAuthorizedFaceFk(String phone,String miliToken,String projectId) {
        R returnVo = new R();
        returnVo.setCode(1);
        returnVo.setMsg("！获取人脸协议失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.get_authorized_face_fk+"?phone="+phone ;

        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        if(StringUtils.isNotBlank(projectId)){
            headers.put("PROJECT-ID",projectId);
        }
        try {
            log.info("获取人脸协议 url  {}", url);
            String resultStr = this.sendGetRequest(url,headers);
            log.info("获取人脸协议 返回值  {}", resultStr);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
            }
            return null;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public R<FangkeNotificationVo> visitorNotification(String miliToken,String projectId) {
        R returnVo = new R();
        returnVo.setCode(1);
        returnVo.setMsg("！访客通知失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this. visitor_notification;

        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        if(StringUtils.isNotBlank(projectId)){
            headers.put("PROJECT-ID",projectId);
        }
        try {
            FangkeNotificationVo fangkeNotificationVo = new FangkeNotificationVo();
            fangkeNotificationVo.setVisitId("f586a520850386650ae0d8241cb5901d");
            fangkeNotificationVo.setRegisterType("1");
            fangkeNotificationVo.setAuditStatus("1");
            fangkeNotificationVo.setVisitorName("黄中林");
            returnVo.setData(fangkeNotificationVo);
            log.info("访客通知 url  {}", url);
            String resultStr = this.sendGetRequest(url,headers);
            if(StringUtils.isNotBlank(resultStr)){
                log.info("访客通知 结果 str  {}", resultStr);
                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
            }
            return returnVo;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 获取访客二维码
     * @param visitId
     * @param miliToken
     * @param projectId
     * @return
     */
    @Override
    public R<FangkeQrCodeVo> getFangkeQrCode(String visitId,String miliToken,String projectId) {
        R returnVo = new R();
        returnVo.setCode(1);
        returnVo.setMsg("！获取访客二维码失败");
        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this. get_visitor_qrcode+visitId;

        Map params = new HashMap();

        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        if(StringUtils.isNotBlank(projectId)){
            headers.put("PROJECT-ID",projectId);
        }
        try {

            log.info("获取访客二维码 url  {}", url);
            log.info("获取访客二维码 请求头  {}",  JSONObject.toJSONString(headers));
            String resultStr = this.sendGetRequest(url,headers);
            if(StringUtils.isNotBlank(resultStr)){
                returnVo = JSONObject.parseObject(resultStr,R.class);
                return returnVo;
            }
            return returnVo;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }





    @Override
    public R<FaceCheckVo> faceUploadAndCheckByBase64(String miliToken, String imageBase64, String projectId) {
        R returnVo = R.errorReturnYuan("！人脸校验失败");

        OkHttpUtil okHttpUtil = OkHttpUtil.getInstance();
        String url = this.face_upload_and_check+"out";



        Map<String,String> headers = new HashMap();
        headers.put("Authorization",miliToken);
        headers.put("TENANT-ID","1");
        if(StringUtils.isNotBlank(projectId)){
            headers.put("PROJECT-ID",projectId);
        }

        // 解码 Base64 字符串
        byte[] decodedBytes = Base64.getDecoder().decode(imageBase64);

        // 处理 URL-safe Base64 字符串
        imageBase64 = imageBase64.replace('-', '+').replace('_', '/');

        // 去除换行符、空格等非法字符
        imageBase64 = imageBase64.replaceAll("[\\n\\r\\s]", "");


        // 生成一个新的文件名，避免文件名冲突
        String newFileName = System.currentTimeMillis() +".jpg";

        // 指定文件保存路径
        //File file = new File("/srv/www/mili/api/uploads/" + newFileName);
        newFileName = "/srv/www/mili/api/uploads/" + newFileName;
        File file = this.convertBase64ToFile(imageBase64,newFileName);
        // 创建文件输出流
        try (FileOutputStream fos = new FileOutputStream(file)) {
            // 将解码后的字节写入文件
            fos.write(decodedBytes);
        }catch (Exception e){
            e.printStackTrace();
        }

        // 创建目录
        file.getParentFile().mkdirs();

        // 将 MultipartFile 保存为 File
        Map<String,Object> params = new HashMap();
        log.info("人脸上传并校验 请求头 : {}", JSONObject.toJSONString(headers));

        try {

            FileInputStream fileInputStreamReader = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()]; // 创建一个字节数组来存储图片数据
            fileInputStreamReader.read(bytes); // 读取图片文件并存储到字节数组中
            //String imageBase64 = Base64.getEncoder().encodeToString(bytes);


            log.info("人脸上传并校验 url : {}",url);
            Map<String,Object> fileMap = new HashMap<>();
            fileMap.put("file",file);
            String resultStr = this.sendMultipartData2(url, params, headers, file);
            //String resultStr = this.sendMultipartData2(url, params, headers, file);
            log.info("人脸上传并校验 返回值 : {}",resultStr);
            if (file.exists() && file.delete()){

            }
            if(StringUtils.isNotBlank(resultStr)){


                returnVo = JSONObject.parseObject(resultStr,R.class);
                if(returnVo.getCode() == 0){
                    JSONObject jsonObject = JSONObject.parseObject(resultStr);
                    FaceCheckVo faceCheckVo = jsonObject.getObject("data", FaceCheckVo.class);
                    faceCheckVo.setImageBase64(imageBase64);
                    returnVo.setData(faceCheckVo);
                }
            }
            return returnVo;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    private  File convertBase64ToFile(String base64String, String filePath) {
        try {
            // 解码 Base64 字符串
            byte[] decodedBytes = Base64.getDecoder().decode(base64String);

            // 创建文件对象
            File file = new File(filePath);

            // 创建文件输出流
            try (FileOutputStream fos = new FileOutputStream(file)) {
                // 将解码后的字节写入文件
                fos.write(decodedBytes);
            }

            return file;
        } catch (IOException e) {
            System.err.println("发生错误: " + e.getMessage());
        }
        return null;
    }

    public String sendGetRequest(String urlString, Map<String,String> header) throws Exception {
        // 创建 URL 对象
        URL url = new URL(urlString);

        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为 GET
        connection.setRequestMethod("GET");

        Set<String> headerKeySet = header.keySet();
        for(String key:headerKeySet){
            connection.setRequestProperty(key, header.get(key));
        }
        // 设置请求头
//        connection.setRequestProperty("Authorization", "Bearer " + authToken);  // 例如使用 Bearer Token
//        connection.setRequestProperty("User-Agent", "Mozilla/5.0");

        // 获取响应码
        int responseCode = connection.getResponseCode();
        System.out.println("Response Code: " + responseCode);

        // 读取响应内容
        StringBuilder response = new StringBuilder();
        if (responseCode == HttpURLConnection.HTTP_OK) {  // 200 OK
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
        } else {
            System.out.println("GET request failed.");
        }

        // 关闭连接
        connection.disconnect();

        // 返回响应内容
        return response.toString();
    }


    private  String sendPostRequest(String urlString, Object param, String contentType, Map<String, String> customHeaders) throws Exception {
        // 创建 URL 对象
        URL url = new URL(urlString);

        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为 POST
        connection.setRequestMethod("POST");

        // 设置默认的请求头
        connection.setRequestProperty("Accept", "application/json");

        // 添加自定义请求头
        if (customHeaders != null) {
            for (Map.Entry<String, String> entry : customHeaders.entrySet()) {
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }

        // 根据不同的 contentType 选择处理方式
        if ("application/x-www-form-urlencoded".equals(contentType)) {
            // 对于 x-www-form-urlencoded 类型，参数为键值对
            connection.setRequestProperty("Content-Type", contentType);
            connection.setDoOutput(true);
            sendFormData(connection, param);
        } else if ("application/json".equals(contentType)) {
            // 对于 JSON 类型，参数为 JSON 字符串
            connection.setRequestProperty("Content-Type", contentType);
            connection.setDoOutput(true);
            sendJsonData(connection, param);
        } else if ("multipart/form-data".equals(contentType)) {
            // 对于文件上传，参数包含文件流
            connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + UUID.randomUUID().toString());
            connection.setDoOutput(true);
            sendMultipartData(connection, param);
        } else {
            throw new UnsupportedOperationException("Unsupported Content-Type: " + contentType);
        }

        // 获取响应状态码
        int statusCode = connection.getResponseCode();

        // 读取响应内容
        StringBuilder response = new StringBuilder();
        try (BufferedReader in = new BufferedReader(new InputStreamReader(
                statusCode >= 400 ? connection.getErrorStream() : connection.getInputStream(), "utf-8"))) {
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
        }

        // 关闭连接
        connection.disconnect();

        // 返回响应内容
        return response.toString();
    }


    // 发送 application/x-www-form-urlencoded 数据
    private static void sendFormData(HttpURLConnection connection, Object param) throws IOException {
        String data = (String) param; // 假设参数为 URL 编码的字符串
        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = data.getBytes("utf-8");
            os.write(input, 0, input.length);
        }
    }

    // 发送 application/json 数据
    private static void sendJsonData(HttpURLConnection connection, Object param) throws IOException {
        String json = (String) param; // 假设参数为 JSON 字符串
        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = json.getBytes("utf-8");
            os.write(input, 0, input.length);
        }
    }




    // 发送 multipart/form-data 数据，支持文件上传
    private static void sendMultipartData(HttpURLConnection connection, Object param) throws IOException {
        String boundary = UUID.randomUUID().toString();
        OutputStream os = connection.getOutputStream();
        log.info("sendMultipartData  :  {}",param instanceof File);
        // 如果 param 是一个文件流
        if (param instanceof File) {
            File file = (File) param;

            // 写入分隔符
            String boundaryPrefix = "--" + boundary + "\r\n";
            os.write(boundaryPrefix.getBytes());

            // 写入字段名和文件信息
            os.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"\r\n").getBytes());
            os.write(("Content-Type: " + "image/jpeg" + "\r\n").getBytes());  // 文件的 MIME 类型
            os.write("\r\n".getBytes());

            // 写入文件内容
            try (FileInputStream fileInputStream = new FileInputStream(file)) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
            }

            // 写入结束标记
            os.write("\r\n".getBytes());
            os.write(("--" + boundary + "--\r\n").getBytes());
        }
    }

    private  String sendMultipartData2(String urlStr,Map<String,Object> params,Map<String,String> headersMap, File file) throws IOException {
            log.info("文件名 {}",file.getName());
        try {
            // 创建 HttpClient 实例
            HttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(urlStr);

            for (Map.Entry<String, String> entry : headersMap.entrySet()) {
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }

            // 设置请求头

            // 构建多部分表单数据
            FileBody fileBody = new FileBody(file, ContentType.create("image/jpeg"));

            HttpEntity entity = MultipartEntityBuilder.create()
                    .addPart("file", fileBody) // "file" 是接口接收文件的参数名
                    .build();

            // 设置请求体
            httpPost.setEntity(entity);

            // 执行请求
            HttpResponse response = httpClient.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            String responseBody = EntityUtils.toString(response.getEntity());

            // 处理响应
            System.out.println("HTTP Status Code: " + statusCode);
            System.out.println("Response Body: " + responseBody);
            return responseBody;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public  String sendPutRequest(String urlString, String jsonPayload, Map<String, String> customHeaders) throws IOException {
        // 创建URL对象
        URL url = new URL(urlString);

        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为 PUT
        connection.setRequestMethod("PUT");

        // 设置允许输入和输出流
        connection.setDoOutput(true);

        // 设置自定义请求头
        if (customHeaders != null) {
            for (Map.Entry<String, String> entry : customHeaders.entrySet()) {
                connection.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }

        // 设置Content-Type为application/json
        connection.setRequestProperty("Content-Type", "application/json");

        // 发送请求数据
        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = jsonPayload.getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        // 获取响应
        int statusCode = connection.getResponseCode();
        InputStream inputStream = (statusCode < HttpURLConnection.HTTP_BAD_REQUEST) ?
                connection.getInputStream() : connection.getErrorStream();

        // 读取响应内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
        StringBuilder response = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }

        // 关闭连接
        connection.disconnect();

        return response.toString();
    }



}
